<script setup>
import { getStore, getStoreByChunks, setStore, setStoreByChunks } from '../services/book-store'
import { getBookChapters, getCurrentTheme, getChapterContent, getBookSourceRule, getBookDetails, SynthesisSpeech } from '../services/bookService'
import pLimit from 'p-limit';
import { ref, onMounted, computed, nextTick, getCurrentInstance } from 'vue';
import { useRouter, useRoute } from 'vue-router';
let { proxy } = getCurrentInstance();
let limit = pLimit(10);
let synthesisSpeech = null;
// 当前阅读的书籍
const book = ref(null);
// 书籍内容
const contents = ref(null);
// 当前章节内容
const content = ref(null);
// 当前章节
const currentChapter = ref(null);
// 章节列表
const chapters = ref([]);
// 显示目录
const showToc = ref(false);
// 当前主题
const currentTheme = ref(null);
// 工具栏显示状态
const showToolbar = ref(false);
// content 元素的 ref
const contentRef = ref(null);
// loading
const loading = ref(false);
// 语音状态 0 未启用 1 播放中 2 暂停
const isPlaying = ref(0);
// 听书进度
const progress = ref({
  sentenceChapter: null,
  sentenceText: null,
});

const route = useRoute();
const router = useRouter();

const setIsPlaying = (type) => {
  isPlaying.value = type;
}
const upProgress = (text) => {
  progress.value = {
    sentenceChapter: currentChapter.value,
    sentenceText: text
  }

  // 更新阅读进度
  book.value.reader = {
    chapter: currentChapter.value,
  };
  setStore('bookshelf', getStore('bookshelf').map(item => {
    if (item._id === book.value._id) {
      return {
        ...book.value,
        reader: {
          chapter: currentChapter.value,
          ...progress.value
        }
      };
    }else{
      return item;
    }
  }))
}

// 切换工具栏显示
const toggleToolbar = () => {
  showToolbar.value = !showToolbar.value;
};

// 切换沉浸模式
const toggleImmersive = () => {
  immersiveMode.value = !immersiveMode.value;
};

// 加载书籍信息
const loadBook = async () => {
  // 从uTools存储中获取当前书籍
  if (window.utools) {
    // 加载主题
    loadTheme();
    getCurrentBook();
    if (book.value) {
      // 模拟加载章节
      await loadChapters();
      // 加载内容
      await loadContent();
      // 初始化听书
      let sentenceText = book.value?.reader?.chapter == book.value?.reader?.sentenceChapter ? book.value?.reader?.sentenceText : '';
      synthesisSpeech = new SynthesisSpeech({setIsPlaying, upProgress, sentenceText});

      await changeChapter(currentChapter.value)
    }
  }
};

// 加载主题
const loadTheme = () => {
  currentTheme.value = getCurrentTheme();
};

// 计算主题样式
const themeStyle = computed(() => {
  if (!currentTheme.value) return {};

  // 设置 css 变量
  document.documentElement.style.setProperty('--color', currentTheme.value.color);
  document.documentElement.style.setProperty('--bg-color', currentTheme.value.backgroundColor);
  
  return {
    backgroundColor: currentTheme.value.backgroundColor,
    color: currentTheme.value.color,
    fontSize: `${currentTheme.value.fontSize}px`,
    lineHeight: currentTheme.value.lineHeight,
    letterSpacing: `${currentTheme.value.letterSpacing}px`,
    fontFamily: currentTheme.value.fontFamily
  };
});

const getCurrentBook = () => {
  let _id = route.query.id;
  const bookshelf = getStore('bookshelf');
  book.value = bookshelf.find(item => item._id === _id);
};

// 加载章节列表
const loadChapters = async () => {
  let _id = book.value._id;
  chapters.value = getStoreByChunks(`${_id}_toc`);
        
  if(!chapters.value || !chapters.value.length){
    try {
      proxy.$toast.info('资源加载中请稍等...');
      let bookSourceRule = getBookSourceRule(book.value);
      let detail = await getBookDetails(book.value, bookSourceRule);
      chapters.value = await getBookChapters(detail);
    } catch (error) {
      console.log(error);
      proxy.$toast.error('资源加载错误');
      chapters.value = [];
    }
    setStoreByChunks(`${_id}_toc`, chapters.value);
  }
  currentChapter.value = book.value?.reader?.chapter || (chapters.value[0]?.id);
};

// 并行获取当前阅读章节前后内容
const getCurrentChapterPrevNextContent = async (chapter = 5) => {
  loading.value = true;
  let bookSourceRule = getBookSourceRule(book.value);
  let index = chapters.value.findIndex((item) => item.id === currentChapter.value);
  let min = Math.max(index - chapter, 0);
  let max = Math.min(index + chapter + 1, chapters.value.length);
  let tasks = chapters.value.map((element, index) => limit(async()=>{
    if (index < min || index > max) return;
    if(element.cache)return;
    for (let i = 0; i < 3 + 1; i++) {
      if(i > 0){ console.log('第'+(i)+'次重试'); }
      try {
        const content = await getChapterContent(element.url, bookSourceRule)
        element.cache = true;
        contents.value[element.id] = {
          id: element.id,
          ...content
        }
        break;
      } catch (error) {
        element.cache = false;
        console.log(error);
        contents.value[element.id] = {
          id: element.id,
          title: element.title,
          content: '加载失败'
        }
        if(i === 3)proxy.$toast.error('资源加载错误');
      }
    }
  }))

  await Promise.allSettled(tasks);
  loading.value = false;
  setStoreByChunks(`${book.value._id}_toc`, chapters.value);
  setStoreByChunks(`${book.value._id}_content`, contents.value);
  
}

// 加载内容
const loadContent = async () => {
  let _id = book.value._id;
  contents.value = getStoreByChunks(`${_id}_content`) || [];
  if(!contents.value || !contents.value.length){
    // 获取内容
    await getCurrentChapterPrevNextContent();
  }
};

// 切换章节
const changeChapter = async (chapterId) => {
  synthesisSpeech.stop();
  currentChapter.value = chapterId;
  let index = chapters.value.findIndex((item) => item.id === chapterId);
  let chapter = chapters.value[index];
  
  // 处理在线书籍
  if(chapter?.cache){
    showToc.value = false;
    content.value = contents.value.find(item => item?.id === chapter.id);
    await nextTick();
    // 滚动到顶部
    contentRef.value && contentRef.value.scrollTo({ top: 0, left: 0, behavior: 'instant' });
  }
  if(!loading.value && !chapter?.cache){
    await getCurrentChapterPrevNextContent()
    content.value = contents.value.find((item) => item?.id === chapter.id);
    await nextTick();
    showToc.value = false;
    // 滚动到顶部
    contentRef.value && contentRef.value.scrollTo({ top: 0, left: 0, behavior: 'instant' });
  }
  
  // 检测是否加载后续章节
  if(loading.value)return;
  if(index + 2 < chapters.value.length && !chapters.value[index + 2].cache){
    let bool = chapters.value.slice(index, index + 3).some(item=> !item.cache)
    if(bool)getCurrentChapterPrevNextContent();
  }

  synthesisSpeech.createContentContext(contentRef.value);

  // 更新阅读进度
  book.value.reader = {
    chapter: currentChapter.value,
    ...progress.value
  };
  setStore('bookshelf', getStore('bookshelf').map(item => {
    if (item._id === book.value._id) {
      return book.value;
    }else{
      return item;
    }
  }))
};

// 下一章
const nextChapter = () => {
  let index = chapters.value.findIndex((item) => item.id === currentChapter.value);
  if (index < chapters.value.length - 1) {
    changeChapter(chapters.value[index + 1].id);
  }
};

// 上一章
const prevChapter = () => {
  let index = chapters.value.findIndex((item) => item.id === currentChapter.value);
  if (index > 0) {
    changeChapter(chapters.value[index - 1].id);
  }
};

// 切换目录显示
const toggleToc = () => {
  showToc.value = !showToc.value;
  if(showToc.value){
    document.querySelector(`.chapter-${currentChapter.value}`).scrollIntoView({ behavior: 'smooth' });
  }
};

// 返回书架
const goBack = () => {
  synthesisSpeech.stop();
  router.push('/');
};

// 监听按键 上下滚动  左右切换章节
const handleKeydown = (event) => {
  document.addEventListener('keydown', (event) => {
    if (event.key === 'ArrowUp') {
      // 向下滚动
      contentRef.value.scrollBy({ top: -100, left: 0, behavior: 'smooth' });
      event.preventDefault();
    } else if (event.key === 'ArrowDown') {
      // 向上滚动
      contentRef.value.scrollBy({ top: 100, left: 0,  behavior: 'smooth' });
      event.preventDefault();
    } else if (event.key === 'ArrowLeft') {
      prevChapter();
    } else if (event.key === 'ArrowRight') {
      nextChapter();
    }
  })
}

// 语音控制
const speechHandle = (type) => {
  synthesisSpeech.setPlaying(type);
  if(type === 1 && !synthesisSpeech.speech.speaking){
    synthesisSpeech.speak();
  }
  if(type === 1 && synthesisSpeech.speech.speaking){
    synthesisSpeech.speech.resume();
  }

  if(type === 2){
    synthesisSpeech.pause();
  }
  showToolbar.value = false;
}


onMounted(async() => {
  handleKeydown();
  await loadBook();

  synthesisSpeech.addEventListener('change', (event) => {
    if(event.detail.type === 'end'){
      nextChapter();
    }
  })
});



if(window.utools){
  utools.onPluginEnter(({ code, type, payload, option, from }) => {
    
    if(code === 'Next'){
      synthesisSpeech.next()
    }
    if(code === 'Prev'){
      synthesisSpeech.prev()
    }
    if(code === 'NextChapter'){
      nextChapter()
    }
    if(code === 'PrevChapter'){
      prevChapter()
    }
    if(code === 'Play/Pause'){
      synthesisSpeech.pause()
    }
  });
}

</script>

<template>
  <div class="reader-page">
    <!-- 顶部工具栏 -->
    <div 
      class="reader-header" 
      :class="{ 'hidden': !showToolbar }"
    >
      <div class="back-btn" @click="goBack">
        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
          <path d="M19 12H5M5 12l6-6m-6 6l6 6"/>
        </svg>
      </div>
      <div class="book-title">{{ content ? content.title : '阅读器' }}</div>
      <div class="toc-btn" @click.stop="toggleToc">目录</div>
    </div>

    <!-- 底部工具栏 -->
    <div
      class="reader-footer"
      :class="{ 'hidden':!showToolbar }"
    >
      <div class="speech-btn" @click="speechHandle(1)" v-if="isPlaying === 0">听书</div>
      <div class="speech-btn" @click="speechHandle(2)" v-else-if="isPlaying === 1">暂停</div>
      <div class="speech-btn" @click="speechHandle(1)" v-else-if="isPlaying === 2">继续</div>
    </div>

    <!-- 章节内容 -->
    <div 
      class="reader-content" 
      :style="themeStyle"
      @click="toggleToolbar"
      ref="contentRef"
    >
      <div class="chapter-title">{{ content?.title || '' }}</div>
      <div class="content-text">
        {{ content?.content || '' }}
      </div>
    </div>
    
    <!-- 目录侧边栏 -->
    <div class="toc-sidebar" :class="{ 'show': showToc }">
      <div class="toc-header">
        <h3>目录</h3>
        <div class="close-btn" @click="toggleToc">×</div>
      </div>
      <div class="toc-list">
        <div 
          v-for="chapter in chapters" 
          :key="chapter.id"
          :class="[ 'toc-item' ,`chapter-${chapter.id}` ,{ 'active': chapter.id === currentChapter, 'cache': chapter.cache }]"
          @click="changeChapter(chapter.id)"
        >
          {{ chapter.title }}
        </div>
      </div>
    </div>
    
    <!-- 遮罩层 -->
    <div 
      v-if="showToc" 
      class="overlay"
      @click="toggleToc"
    ></div>
  </div>
</template>

<style scoped>
.reader-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 16px;
  background-color: rgba(0, 0, 0, 0.7);
  color: white;
  z-index: 150;
}

.book-title {
  flex: 1;
  text-align: center;
  font-weight: bold;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  margin: 0 16px;
}

.back-btn, .toc-btn {
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  transition: all 0.3s;
  cursor: pointer;
}

.back-btn:hover, .toc-btn:hover {
  background-color: rgba(255, 255, 255, 0.2);
}

.reader-page {
  position: relative;
  height: 100vh;
  display: flex;
  flex-direction: column;
  /* background-color: #f8f8f0; */
  color: #333;
}

.reader-content {
  box-sizing: border-box;
  flex: 1;
  padding: 16px;
  /* height: 100%; */
  min-height: 100%;
  overflow-y: auto;
  line-height: 1.8;
  white-space: pre-wrap;
}

.reader-content::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

.reader-content::-webkit-scrollbar-track-piece{
  background-color: transparent;
}
.reader-content::-webkit-scrollbar-thumb {
  /* background-color: transparent; */
  background: var(--color);
  border-radius: 3px;
  border-color: var(--color);
}

/* .reader-content::-webkit-scrollbar-thumb:hover {
  background: rgba(51, 136, 255, 0.8);
} */

.chapter-title {
  font-size: 20px;
  font-weight: bold;
  margin-bottom: 20px;
  text-align: center;
}

.content-text p {
  margin-bottom: 1em;
  text-indent: 2em;
}

.reader-footer {
  position: fixed;
  bottom: 20px;
  right: 20px;
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  z-index: 150;
}

.speech-btn{
  width: 50px;
  height: 50px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 14px;
  font-weight: 500;
  border-radius: 50%;
  transition: all 0.3s ease;
  cursor: pointer;
  background-color: var(--blue, #4a90e2);
  box-shadow: 0 4px 10px rgba(74, 144, 226, 0.3);
  border: 2px solid rgba(255, 255, 255, 0.2);
  backdrop-filter: blur(5px);
  transform: translateZ(0);
}

.speech-btn:hover {
  transform: scale(1.05) translateZ(0);
  box-shadow: 0 6px 15px rgba(74, 144, 226, 0.4);
}

.speech-btn:active {
  transform: scale(0.95) translateZ(0);
  box-shadow: 0 2px 8px rgba(74, 144, 226, 0.3);
}
.nav-btn {
  padding: 8px 20px;
  border-radius: 4px;
}

.nav-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.toc-sidebar {
  position: fixed;
  top: 0;
  left: -280px;
  width: 280px;
  height: 100%;
  background-color: #fff;
  box-shadow: 2px 0 8px rgba(0, 0, 0, 0.1);
  transition: left 0.3s;
  z-index: 1000;
}

.toc-sidebar.show {
  left: 0;
}

.toc-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px;
  border-bottom: 1px solid #eee;
}

.toc-header h3 {
  margin: 0;
}

.close-btn {
  font-size: 24px;
  cursor: pointer;
}

.toc-list {
  height: calc(100% - 60px);
  overflow-y: auto;
}

.toc-item {
  padding: 12px 16px;
  border-bottom: 1px solid #f0f0f0;
  cursor: pointer;
  color: #ccc;
}

.toc-item:hover {
  background-color: #f9f9f9;
}

.toc-item.active.cache {
  color: royalblue;
  font-weight: bold;
}

.toc-item.cache {
  color: #333;
}

.overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.3);
  z-index: 999;
}

.reader-header,
.reader-footer {
  transition: opacity 0.3s;
}

.reader-header.hidden,
.reader-footer.hidden {
  opacity: 0;
  pointer-events: none;
}
</style>